package com.seanLab.tool.TagBat;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import org.nlpcn.commons.lang.tire.SmartGetWord;
import org.nlpcn.commons.lang.tire.domain.SmartForest;
import org.nlpcn.commons.lang.util.StringUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

@Deprecated
public class TagsBat {

    //    private static String articlesPath = "chens.article_10171458_3.json";
    private static String articlesPath = "workingDir" + File.separator + "chens.article_10231928_small_1.json";
    //    private static String imagesPath = "chens.image_10171458.json";
    private static String imagesPath = "workingDir" + File.separator + "chens.validImage_10231928.json";
    private static int threadNum = 4;
    //    private static int currentPartition = 1;
//    private static int totalPartition = 1;
    private List<JsonObject> articlesJson;
    private List<JsonObject> imagesJson;
    private HashMap<String, JsonObject> imagesIndex;

    private List<JsonObject> articlesResult = new LinkedList<>();
    private List<JsonObject> imagesResult = new LinkedList<>();

    private SmartForest<JsonObject> imagesForest;


    private void loadArticles(String articlesPath) throws IOException {
//        this.articlesPath = articlesPath;
        JsonParser jsonParser = new JsonParser();
        articlesJson = new ArrayList<>();

        JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(articlesPath)));
        reader.beginArray();
//        int count = 0;
        while (reader.hasNext()) {
//            JsonObject articleJson = jsonParser.parse(reader).getAsJsonObject();
            articlesJson.add(jsonParser.parse(reader).getAsJsonObject());
//            count++;
        }
        reader.close();
        System.out.println("Articles size: " + articlesJson.size());
    }

    private void loadImages(String imagesPath) throws IOException{
//        this.imagesPath = imagesPath;
        JsonParser jsonParser = new JsonParser();
        imagesJson = new LinkedList<>();

        JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(imagesPath)));
        reader.beginArray();
        while (reader.hasNext()) {
            imagesJson.add(jsonParser.parse(reader).getAsJsonObject());
        }
        reader.close();
        System.out.println("Images size: " + imagesJson.size());
    }

    private void buildIndex() {
        imagesIndex = new HashMap<>();
        long start = System.currentTimeMillis();
        for (JsonObject image : imagesJson) {
            imagesIndex.put(image.get("_id").getAsString(), image);
        }
        long end = System.currentTimeMillis();
        System.out.println("hash map time: " + String.valueOf(end - start));

//        imagesForest = new SmartForest<>();
//        start = System.currentTimeMillis();
//        for (JsonObject image : imagesJson) {
//            imagesForest.add(image.get("_id").getAsString(), image);
//        }
//        end = System.currentTimeMillis();
//        System.out.println("trie map time: " + String.valueOf(end - start));

        System.out.println("Index size: " + imagesIndex.size());
    }

    private void testIndex() {
//        long start = System.currentTimeMillis();
//        for (String id : imagesIndex.keySet()) {
//            JsonObject json = imagesIndex.get(id);
//        }
//        long end = System.currentTimeMillis();
//        System.out.println("hash map test time: " + String.valueOf(end - start));
//
//        start = System.currentTimeMillis();
//        for (String id : imagesIndex.keySet()) {
//            JsonObject json = imagesForest.getBranch(id).getParam();
//        }
//        end = System.currentTimeMillis();
//        System.out.println("trie map test time: " + String.valueOf(end - start));
        for (String id : imagesIndex.keySet()) {
            if (imagesIndex.get(id) != imagesForest.getBranch(id).getParam()) {
                System.out.println(id);
                break;
            }
        }
    }

    private void parallel(int threadNum) throws IOException {

        TagThread[] threads = new TagThread[threadNum];
        int size = articlesJson.size();
        for (int i = 0; i < threadNum; i++) {
            List<JsonObject> subList = articlesJson.subList(i * size / threadNum, (i + 1) * size / threadNum);
            threads[i] = new TagThread(subList, imagesIndex);
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threadNum; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            articlesResult.addAll(threads[i].articlesResult);
            imagesResult.addAll(threads[i].imagesResult);
        }
        String articlesResultPath = articlesPath.replace(".json", "_result.json");
        String imagesResultPath = articlesPath.replace(".json", "_images_result.json");
//        String articlesResultPath = articlesPath.replace(".json", "_result" + currentPartition + ".json");
//        String imagesResultPath = imagesPath.replace(".json", "_result" + currentPartition + ".json");

//        Gson gson = new GsonBuilder().setPrettyPrinting().create();
//        gson.toJson(articlesResult, new FileWriter(articlesResultPath));
//        gson.toJson(imagesResult, new FileWriter(imagesResultPath));
        saveJson(articlesResult, articlesResultPath);
        saveJson(imagesResult, imagesResultPath);
        System.out.println(end - start + "ms with " + threadNum + " thread");
    }

    private void saveJson(Object obj, String path) throws IOException {
        OutputStream outputStream = new FileOutputStream(path);
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        new GsonBuilder().setPrettyPrinting().create().toJson(obj, bufferedWriter);
        bufferedWriter.close();
    }

    public static void main(String[] args) throws IOException {
        System.out.println("Good Luck!");
        if (args.length > 0) {
            threadNum = Integer.parseInt(args[0]);
        }
        if (args.length > 1) {
            articlesPath = args[1];
        }
        if (args.length > 2) {
            imagesPath = args[2];
        }
        System.out.println(threadNum + " " + articlesPath + " " + imagesPath);
//        if (args.length > 4) {
//            currentPartition = Integer.parseInt(args[3]);
//            totalPartition = Integer.parseInt(args[4]);
//
//            System.out.println(currentPartition + "/" + totalPartition);
//        }
        TagsBat main = new TagsBat();
        main.loadImages(imagesPath);
        main.buildIndex();
//        main.testIndex();
        main.loadArticles(articlesPath);
        main.parallel(threadNum);
//        main.parallel(2);
//        main.parallel(3);
//        main.parallel(4);
//        main.parallel(5);
//        main.parallel(6);
//        System.out.println();
    }

    public static class SmartGetWordTest {

        public static void main(String[] args){
            /**
             * 词典的构造.一行一个词后面是参数.可以从文件读取.可以是read流.
             */
            long start = System.currentTimeMillis();
            SmartForest<Integer> forest = new SmartForest<Integer>();

            forest.add("中国", 3);

            forest.add("android", 3);

            forest.add("java", 3);

            forest.add("中国人", 3);

            String content = " Android-java-中国人";
            content = StringUtil.rmHtmlTag(content);

            for (int i = 0; i < 1; i++) {
                SmartGetWord<Integer> udg = forest.getWord(content.toLowerCase().toCharArray());

                String temp = null;
                while ((temp = udg.getFrontWords()) != null) {
                    System.out.println(temp + "\t" + udg.getParam());
                }
            }
            System.out.println(System.currentTimeMillis() - start);
        }

    }
}
